package com.yupi.springbootinit.listener;

import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.rabbitmq.client.Channel;
import com.yupi.springbootinit.model.entity.Order;
import com.yupi.springbootinit.service.OrderService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.RabbitListener;

import javax.annotation.Resource;
import java.io.IOException;

import static com.yupi.springbootinit.constant.RabbitMqConstant.QUEUE_ORDER_DLX_QUEUE;

/**
 * @author wzh
 */
@Slf4j
public class OrderTimeOutListener {

    @Resource
    private OrderService orderService;


    public static final Integer ORDER_UNPAY_STATUS = 0;


    public static final Integer ORDER_TIMEOUT_STATUS = 8;

    //监听queue_order_dlx_queue死信队列，实现支付超时的回滚功能
    //生产者是懒加载机制，消费者是饿汉加载机制，二者机制不对应，所以消费者要自行创建队列并加载，否则会报错
    @RabbitListener(queuesToDeclare = { @Queue(QUEUE_ORDER_DLX_QUEUE)})
    public void receiveOrderMsg(Order order, Message message, Channel channel) throws IOException {
       log.info("监听到消息:"+order.toString());
        Order dbOrder = orderService.getById(order.getOrderId());
//         根据订单的状态判断订单是否支付，没有支付则进行库存的回滚
       if (dbOrder.getOrderStatus().equals(ORDER_UNPAY_STATUS)){
           Integer bookId = dbOrder.getBookId();
           Integer bookNum = dbOrder.getBookNum();
           try {
               boolean success = orderService.recoverInterfaceStock(bookId, bookNum);
               if (!success){
                   log.error("回滚库存失败");
//                   是否批量处理，是否重新投递,表示消息会被重新放回队列进行消费
                   channel.basicNack(message.getMessageProperties().getDeliveryTag(),false,true);
               }
               UpdateWrapper<Order> updateWrapper=new UpdateWrapper<>();
//                  更改订单状态为超时
              updateWrapper.set("status",ORDER_TIMEOUT_STATUS);
              updateWrapper.eq("id",order.getOrderId());
               orderService.update(updateWrapper);
           } catch (Exception e) {
               log.error("回滚库存失败!!!");
               e.printStackTrace();
               // 消费者告知消息队列无法处理特定消息，并且不希望消息重新投递
//               投递失败会放回消息队列，可能会产生消息堆积的问题
               channel.basicReject(message.getMessageProperties().getDeliveryTag(),true);
           }
//            手动确认消息被消费
           channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
       }
    }
}
